﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CarbonExchange.Bll;

namespace CarbonExchange.Tests
{
    [TestClass]
    public class TemplateTests : BaseTest
    {
        [TestMethod]
        public void Template_GetById_WithIncorrectId_ReturnsNull()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            Assert.IsNull(factory.GetById(int.MaxValue));
        }

        [TestMethod]
        public void Template_GetById_WithCorrectId_ReturnsNotNull()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            Assert.IsNotNull(factory.GetById(_TestTemplates[0].Id));
        }

        [TestMethod]
        public void Template_GetById_PopulatesCorrectly()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = factory.GetById(_TestTemplates[0].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.Id);
            Assert.AreEqual(_TestTemplates[0].ExcludeFromSearch, tmp.ExcludeFromSearch);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.Name);
            Assert.AreEqual(_TestTemplates[0].Notes, tmp.Notes);
            Assert.AreEqual(_TestTemplates[0].SiteId, tmp.SiteId);
            Assert.AreEqual(_TestTemplates[0].CID, tmp.CID);
        }

        [TestMethod]
        public void Template_GetAllBySiteId_WithIncorrectId_ReturnsEmptyList()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            Assert.AreEqual(0, factory.GetAllBySiteId(int.MaxValue).ToList().Count);
        }

        [TestMethod]
        public void Template_GetAllBySiteId_WithCorrectId_ReturnsNotEmptyList()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            Assert.AreEqual(_TestTemplates.Count, factory.GetAllBySiteId(_TestSite.Id).ToList().Count);
        }

        [TestMethod]
        public void Template_GetAllBySiteId_PopulatesCorrectly()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmpList = factory.GetAllBySiteId(_TestSite.Id);
            Assert.IsNotNull(tmpList);
            foreach(Template tmp in tmpList)
            {
                var i = _TestTemplates.FindIndex(x => x.Id == tmp.Id);
                Assert.AreEqual(_TestTemplates[i].Id, tmp.Id);
                Assert.AreEqual(_TestTemplates[i].ExcludeFromSearch, tmp.ExcludeFromSearch);
                Assert.AreEqual(_TestTemplates[i].Name, tmp.Name);
                Assert.AreEqual(_TestTemplates[i].Notes, tmp.Notes);
                Assert.AreEqual(_TestTemplates[i].SiteId, tmp.SiteId);
                Assert.AreEqual(_TestTemplates[i].CID, tmp.CID);
            }
        }

        [TestMethod]
        public void Template_DeleteOne()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = factory.GetById(_TestTemplates[0].Id);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestTemplates[0].Id));
            Assert.AreEqual(_TestTemplates.Count - 1, factory.GetAllBySiteId(_TestSite.Id).Count());
        }

        [TestMethod]
        public void Template_DeleteMany()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = factory.GetAllBySiteId(_TestSite.Id);
            factory.Delete(tmp);
            Assert.IsNull(factory.GetById(_TestTemplates[0].Id));
            Assert.AreEqual(0, factory.GetAllBySiteId(_TestSite.Id).Count());
        }

        [TestMethod]
        public void Template_UpdateOne()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = factory.GetById(_TestTemplates[0].Id);
            Assert.IsNotNull(tmp);
            Assert.IsFalse(tmp.ExcludeFromSearch);
            tmp.Name = "Update Test Name";
            tmp.Notes = "Update Test Notes";
            tmp.ExcludeFromSearch = !tmp.ExcludeFromSearch;
            factory.Save(tmp);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.Id);
            Assert.AreEqual("Update Test Name", tmp.Name);
            Assert.AreEqual("Update Test Name", tmp.Name);
            Assert.AreEqual("Update Test Notes", tmp.Notes);
            Assert.IsTrue(tmp.ExcludeFromSearch);

            tmp = factory.GetById(tmp.Id);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.Id);
            Assert.AreEqual("Update Test Name", tmp.Name);
            Assert.AreEqual("Update Test Name", tmp.Name);
            Assert.AreEqual("Update Test Notes", tmp.Notes);
            Assert.IsTrue(tmp.ExcludeFromSearch);
        }

        [TestMethod]
        public void Template_UpdateMany()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmpList = factory.GetAllBySiteId(_TestSite.Id).ToList();
            int i = 0;
            foreach (Template tmp in tmpList)
            {
                tmp.Name = "Update Test Name {0}".Format(i);
                tmp.Notes = "Update Test Notes {0}".Format(i);
                tmp.ExcludeFromSearch = i % 2 == 0;
                i++;
            }

            factory.Save(tmpList);

            i = 0;
            foreach (Template tmp in tmpList)
            {
                Assert.AreEqual("Update Test Name {0}".Format(i), tmp.Name);
                Assert.AreEqual("Update Test Notes {0}".Format(i), tmp.Notes);
                Assert.AreEqual(i % 2 == 0, tmp.ExcludeFromSearch);
                i++;
            }

            i = 0;
            foreach (Template tmp in factory.GetAllBySiteId(_TestSite.Id))
            {
                Assert.AreEqual("Update Test Name {0}".Format(i), tmp.Name);
                Assert.AreEqual("Update Test Notes {0}".Format(i), tmp.Notes);
                Assert.AreEqual(i % 2 == 0, tmp.ExcludeFromSearch);
                i++;
            }

        }

        [TestMethod]
        public void Template_InsertOne()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = new Template(_AlternateSite.Id);
            tmp.Name = "Insert Test";
            tmp.Notes = "Inset test notes";
            tmp.ExcludeFromSearch = true;
            factory.Save(tmp);

            Assert.IsTrue(tmp.Id != 0);
            Assert.AreEqual("Insert Test", tmp.Name);
            Assert.AreEqual("Inset test notes", tmp.Notes);
            Assert.AreEqual(_AlternateSite.Id, tmp.SiteId);
            Assert.IsTrue(tmp.ExcludeFromSearch);
            Assert.IsNotNull(tmp.CID);

            var tmp2 = factory.GetById(tmp.Id);
            Assert.AreEqual(tmp.Id, tmp2.Id);
            Assert.AreEqual(tmp.CID, tmp2.CID);
            Assert.AreEqual(tmp.ExcludeFromSearch, tmp2.ExcludeFromSearch);
            Assert.AreEqual(tmp.Name, tmp2.Name);
            Assert.AreEqual(tmp.Notes, tmp2.Notes);
            Assert.AreEqual(tmp.SiteId, tmp2.SiteId);

            Assert.AreEqual(1, factory.GetAllBySiteId(_AlternateSite.Id).Count());
        }

        [TestMethod]
        public void Template_InsertMany()
        {
            int noToGen = 3;
            TemplateFactory factory = new TemplateFactory(_Context);
            List<Template> tmpList = new List<Template>();
            for (int i = 0; i < noToGen; i++)
            {
                var tmp = new Template(_AlternateSite.Id);
                tmp.Name = "Insert Test {0}".Format(i);
                tmp.Notes = "Inset test notes {0}".Format(i);
                tmp.ExcludeFromSearch = i % 2 == 0;
                tmpList.Add(tmp);
            }

            factory.Save(tmpList);
            foreach (var tmp in tmpList)
            {
                var i = tmpList.IndexOf(tmp);
                Assert.IsTrue(tmp.Id != 0);
                Assert.AreEqual("Insert Test {0}".Format(i), tmp.Name);
                Assert.AreEqual("Inset test notes {0}".Format(i), tmp.Notes);
                Assert.AreEqual(_AlternateSite.Id, tmp.SiteId);
                Assert.AreEqual(i % 2 == 0, tmp.ExcludeFromSearch);
                Assert.IsNotNull(tmp.CID);
            }
            var tmpList2 = factory.GetAllBySiteId(_AlternateSite.Id).ToList();
            Assert.AreEqual(noToGen, tmpList2.Count());
            foreach (var tmp in tmpList)
            {
                var tmp2 = tmpList2[tmpList.IndexOf(tmp)];
                Assert.AreEqual(tmp.Id, tmp2.Id);
                Assert.AreEqual(tmp.CID, tmp2.CID);
                Assert.AreEqual(tmp.ExcludeFromSearch, tmp2.ExcludeFromSearch);
                Assert.AreEqual(tmp.Name, tmp2.Name);
                Assert.AreEqual(tmp.Notes, tmp2.Notes);
                Assert.AreEqual(tmp.SiteId, tmp2.SiteId);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void Template_SiteIdNotSet_ThowsException()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = new Template(0);
            factory.Save(tmp);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void Template_NameNotSet_ThowsException()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = new Template(_TestSite.Id);
            factory.Save(tmp);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void Template_DuplicateName_ThowsException()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = new Template(_TestSite.Id);
            tmp.Name = _TestTemplates[0].Name;
            factory.Save(tmp);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void Template_DuplicateName_InsertMany_ThowsException()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmpList = new Template[2];
            for (int i = 0; i < tmpList.Count(); i++)
            {
                tmpList[i] = new Template(_AlternateSite.Id);
                tmpList[i].Name = "Duplicate";
            }
            factory.Save(tmpList);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ConcurencyException))]
        public void Template_ConcurencyTest()
        {
            TemplateFactory factory = new TemplateFactory(_Context);
            var tmp = factory.GetById(_TestTemplates[0].Id);
            var tmp2 = factory.GetById(_TestTemplates[0].Id);
            tmp.Name = "ConcurencyTest";
            tmp2.Name = "ConcurencyTest2";
            factory.Save(tmp);
            factory.Save(tmp2);
        }

    }
}
